'use strict'
/**
 * @Description: 校验
 * @Author: Zander
 * @Date: 2022/11/28 13:58
 * @LastEditors: Zander
 * @LastEditTime: 2022/11/28 13:58
 */
const toString = Object.prototype.toString

/**
 * 变量类型判断
 * @param value
 * @param type
 * @returns {boolean}
 */
export function is(value, type) {
  return toString.call(value) === `[object ${type}]`;
}

/**
 * 判断一个值是否是undefined类型
 * @param value
 * @returns {boolean}
 */
export function isUndefined(value) {
  return is(value, 'Undefined')
}

/**
 * 判断一个值是否是日期
 * @param value
 * @returns {boolean}
 */
export function isDate(value) {
  return is(value, 'Date')
}

/**
 * 判断一个值是否是null类型
 * @param value
 * @returns {boolean}
 */
export function isNull(value) {
  return is(value, 'Null')
}

/**
 * 判断一个值是否是null类型且未定义
 * @param value
 * @returns {boolean}
 */
export function isNullAndUnDef (value) {
  return isUndefined(value) && isNull(value)
}

/**
 * 判断一个值是否是null类型或未定义
 * @param value
 * @returns {boolean}
 */
export function isNullOrUnDef(value) {
  return isUndefined(value) || isNull(value)
}

/**
 * 判断一个值是否是number类型
 * @param value
 * @returns {boolean}
 */
export function isNumber(value) {
  return is(value, 'Number')
}

/**
 * 判断一个值是否是string类型
 * @param value
 * @returns {boolean}
 */
export function isString(value) {
  return is(value, 'String')
}

/**
 * 判断一个值是否是function类型
 * @param value
 * @returns {boolean}
 */
export function isFunction(value) {
  return is(value, 'Function')
}

/**
 * 判断一个值是否是Boolean值
 * @param value
 * @returns {boolean}
 */
export function isBoolean(value) {
  return is(value, 'Boolean')
}

/**
 * 判断一个值是否是RegExp值
 * @param value
 * @returns {boolean}
 */
export function isRegExp(value) {
  return is(value, 'RegExp')
}

/**
 * 判断一个值是否是一个数组
 * @param value
 * @returns {arg is any[]}
 */
export function isArray(value) {
  return value && Array.isArray(value)
}

/**
 * 判断一个值是否是一个对象
 * @param value
 * @returns {boolean}
 */
export function isObject(value) {
  return value !== null && value !== undefined && is(value, 'Object')
}

/**
 * 判断一个值是否是一个Promise对象
 * @param value
 * @returns {boolean}
 */
export function isPromise(value) {
  return is(value, 'Promise') && isObject(value) && isFunction(value.then) && isFunction(value.catch)
}

/**
 * 判断一个值是否是一个Window对象
 * @param value
 * @returns {boolean}
 */
export function isWindow(value) {
  return typeof window !== 'undefined' && is(value, 'Window')
}

/**
 * 判断一个值是否是一个Element对象
 * @param value
 * @returns {boolean}
 */
export function isElement(value) {
  return isObject(value) && !!value.tagName
}

/**
 * 判断一个值是否是一个Map对象
 * @param value
 * @returns {boolean}
 */
export function isMap(value) {
  return is(value, 'Map')
}

/**
 * 判断一个值是否为空
 * @param value
 * @returns {boolean}
 */
export function isEmpty(value) {
  if (isArray(value) || isString(value)) {
    return value.length === 0
  }

  if (isNull(value) || isUndefined(value)) {
    return true
  }

  if (value instanceof Map || value instanceof Set) {
    return value.size === 0
  }

  if (isObject(value)) {
    return Object.keys(value).length === 0
  }

  return false
}

/**
 * 判断一个值是否是URL
 * @param url
 * @returns {boolean}
 */
export function isUrl (url) {
  const reg =
    /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return reg.test(url)
}

/**
 * 判断一个值是否是邮箱
 * @param email
 * @returns {boolean}
 */
export function isEmail (email) {
  const reg = /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/
  return reg.test(email)
}

/**
 * 判断是外链
 * @param path
 * @returns {boolean}
 */
export function isExternal (path) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

/**
 * 判断小写
 * @param str
 * @returns {boolean}
 */
export function validLowerCase (str) {
  const reg = /^[a-z]+$/
  return reg.test(str)
}

/**
 * 判断大写
 * @param str
 * @returns {boolean}
 */
export function validUpperCase (str) {
  const reg = /^[A-Z]+$/
  return reg.test(str)
}

/**
 * 判断一个值是否是URLSearchParams对象
 * @param value
 * @returns {boolean}
 */
export function isURLSearchParams(value) {
  return typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams
}

/**
 * 判断URL是否为绝对URL
 * @param url 要测试的url
 * @returns {boolean} 如果URL是绝对URL，则为True，否则为false
 */
export function isAbsoluteURL(url) {
  // 如果一个URL以"://"或"//"(协议相关的URL)开头，它就被认为是绝对的。
  // RFC 3986将scheme name定义为以字母开头，后跟的字符序列
  // 通过字母、数字、加号、句号或连字符的任意组合。
  return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
}

/**
 * 判断是否是Base64
 * @param str
 * @returns {boolean}
 */
export function isBase64(str) {
  if (isEmpty(str)) {
    return false
  }
  const reg = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*?)\s*$/i;
  if (reg.test(str)) {
    return true;
  }
  try {
    return btoa(atob(str)) === str;
  } catch (e) {
    return false;
  }
}
